package org.robot.scm.utils;

import cn.hutool.db.Db;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.db.Entity;
import cn.hutool.db.ds.simple.SimpleDataSource;
import java.util.List;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.robot.scm.infra.ScmTable;

@Slf4j
public class SQLiteUtil {

    /**
     * 默认数据源
     */
    private static final SimpleDataSource source = new SimpleDataSource("jdbc:sqlite:config/scm.db", null, null);

    /**
     * 新增记录
     */
    public static <T> boolean insert(T bean) {
        if (Objects.isNull(bean)) {
            return false;
        }
        try {
            Entity object = Entity.parse(bean, true, true);
            setTable(object, bean);
            return Db.use(source).insert(object) > 0;
        } catch (Exception e) {
            throw new DbRuntimeException(e);
        }
    }

    /**
     * 删除记录
     */
    public static <T> boolean delete(T bean) {
        try {
            Entity object = Entity.parse(bean, true, true);
            setTable(object, bean);
            return Db.use(source).del(object) > 0;
        } catch (Exception e) {
            throw new DbRuntimeException(e);
        }
    }

    /**
     * 查询记录
     */
    public static <T> List<T> query(String sql, Class<T> clazz) {
        try {
            List<Entity> results = Db.use(source).query(sql);
            return StreamUtils.convert(results, e -> e.toBean(clazz));
        } catch (Exception e) {
            throw new DbRuntimeException(e);
        }
    }

    /**
     * 根据类型统计数量
     */
    public static <T> Long count(Class<T> clazz) {
        try {
            T t = clazz.getDeclaredConstructor().newInstance();
            Entity entity = Entity.parse(t, true, true);
            setTable(entity, t);
            List<Entity> query = Db.use(source).query("select count(*) from " + entity.getTableName());
            if (CollectionUtils.isEmpty(query)) {
                return 0L;
            }
            return query.get(0).getLong("count(*)");
        } catch (Exception e) {
            throw new DbRuntimeException(e);
        }
    }

    /**
     * 根据条件统计数量
     */
    public static <T> Long count(T bean) {
        try {
            Entity entity = Entity.parse(bean, true, true);
            setTable(entity, bean);
            return (long) Db.use(source).find(entity).size();
        } catch (Exception e) {
            throw new DbRuntimeException(e);
        }
    }

    /**
     * 更新记录
     */
    public static <T> boolean update(T updateBean, T whereBean) {
        try {
            Entity updateEntity = Entity.parse(updateBean, true, true);
            setTable(updateEntity, updateBean);
            Entity whereEntity = Entity.parse(whereBean, true, true);
            setTable(whereEntity, whereBean);
            return Db.use(source).update(updateEntity, whereEntity) > 0;
        } catch (Exception e) {
            throw new DbRuntimeException(e);
        }
    }

    /**
     * 自动设置表
     */
    private static <T> void setTable(Entity entity, T bean) {
        ScmTable annotation = bean.getClass().getDeclaredAnnotation(ScmTable.class);
        if (Objects.isNull(annotation) || StringUtils.isBlank(annotation.value())) {
            throw new DbRuntimeException("@ScmTable annotation need on {}", bean.getClass().getSimpleName() + ".class");
        }
        entity.setTableName(annotation.value());
    }

}
